import sys
import itertools

from game_runner import GameRunner
from Quoridor_game import WHITE, BLACK, TIE, QuoridorState
from quoridor_agents import AGENTS

DEFAULT_TURN_TIME_LIMIT = 60.0
DEFAULT_SETUP_TIME_LIMIT = 1.0

def playGame((agent1, agent1_name), (agent2, agent2_name),
             game_number, setup_time_limit, turn_time_limit):
  agents = { WHITE: agent1(1,100,0), BLACK: agent2(1,100,0) }
  agent_names = { WHITE: agent1_name, BLACK: agent2_name, TIE: None, None: None }
  state = QuoridorState(2)
  print "*"*80
  print "Running Game %d [Turn Time Limit: %f]:" % (game_number, turn_time_limit)
  print "%s: %s (%s)" % (WHITE, agent1_name, agent1.__name__)
  print "%s: %s (%s)" % (BLACK, agent2_name, agent2.__name__)
  print "*"*80
  winner = GameRunner(state, agents, turn_time_limit, setup_time_limit).run()
  if winner is None or winner == TIE:
    print "TIE!"
  else:
    print "WINNER: %s (%s)" % (agent_names[winner], winner)
  print "*"*80
  return (winner, agent_names[winner])

def playTournamentForTime(agent_names, setup_time_limit, turn_time_limit):
  game_agents = []
  for agent_name in agent_names:
    if agent_name not in AGENTS.keys():
      print "Error: Agent '%s' is not recognized and is ignored!" % agent_name
      print "       (It should be in AGENTS dictionary)"
    else:
      game_agents.append((AGENTS[agent_name], agent_name))
  if len(game_agents) < 2:
    print "Error: Must have 2 agents or more to compare! (Got %d)" % len(game_agents)
    print "  AGENTS = %s" % ", ".join(AGENTS.keys())
    return

  players = []
  winners = []
  game_number = 1
  for current_agents in itertools.permutations(game_agents, 2):
    current_players = [(WHITE, current_agents[0][1]), (BLACK, current_agents[1][1])]
    winner, winner_name = playGame(
        current_agents[0], current_agents[1], game_number,
        setup_time_limit, turn_time_limit)
    players.append(current_players)
    winners.append((winner, winner_name))
    game_number += 1

  return (players, winners)

def playTournament(agent_names, setup_time_limits, turn_time_limits):
  results = {}
  for (setup_time_limit, turn_time_limit) in itertools.product(setup_time_limits, turn_time_limits):
    results[(setup_time_limit, turn_time_limit)] = playTournamentForTime(
        agent_names, setup_time_limit, turn_time_limit)
  return results

def printSummary(results):
  print
  print 'Summary:'
  for ((setup_time_limit, turn_time_limit), (players, winners)) in results.items():
    print '  Setup Time Limit = %f, Turn Time Limit = %f:' % (
        setup_time_limit, turn_time_limit)
    for (i, (winner, winner_name)) in enumerate(winners):
      if winner != TIE:
        print '    Game %d WINNER: %-30s [%s]' % (
            i+1, ("(%s) %s" % (winner, winner_name)),
            ", ".join(["%s: %-20s" % player for player in players[i]]))
      else:
        print '    Game %d TIED: %-30s [%s]' % (
            i+1, " ",
            ", ".join(["%s: %-20s" % player for player in players[i]]))

def exportResultsToCSV(export_to_csv, results):
  col_names = ["Agent1", "Agent2", "Turn Time Limit", "Setup Time Limit",
               "Winner Agent", "Winner Player", "Agent1 Won", "Agent2 Won",
               "1st Won", "2nd Won"]
  table_str = ",".join(["'" + str(col) + "'" for col in col_names]) + "\n"

  for ((setup_time_limit, turn_time_limit), (players, winners)) in results.items():
    for (i, (winner, winner_name)) in enumerate(winners):
      if winner != TIE:
        cols = [players[i][0][1], players[i][1][1], turn_time_limit, setup_time_limit,
                winner_name, winner, int(winner == WHITE), int(winner == BLACK),
                int(winner == WHITE), int(winner == BLACK)]
      else:
        cols = [players[i][0][1], players[i][1][1], turn_time_limit, setup_time_limit,
                None, winner, 0, 0, 0, 0]
      table_str += ",".join([str(col) for col in cols]) + "\n"

  f = open(export_to_csv, "w")
  f.write(table_str)
  f.flush()
  f.close()

  print
  print "Exported results to CSV: '%s'" % export_to_csv
  
if __name__ == "__main__":
  turn_time_limits = [DEFAULT_TURN_TIME_LIMIT]
  setup_time_limits = [DEFAULT_SETUP_TIME_LIMIT]
  max_turns = 100
  export_to_csv = None

  agent_names = []
  for arg in sys.argv[1:]:
    if arg.startswith("t="):
      arg = arg[2:]
      try:
        turn_time_limits = [float(arg)]
      except:
        turn_time_limits = [float(a) for a in arg.split(",")]
    elif arg.startswith("s="):
      arg = arg[2:]
      try:
        setup_time_limits = [float(arg)]
      except:
        setup_time_limits = [float(a) for a in arg.split(",")]
    elif arg.startswith("m="):
      max_turns = int(arg[2:])
    elif arg.startswith("csv="):
      export_to_csv = arg[len("csv="):]
    else:
      agent_names.append(arg)

  print "="*80
  print
  print "Starting Tournament:"
  print "Agents: %s" % ", ".join(agent_names)
  print "Setup Time Limits: %s" % ", ".join([str(val) for val in setup_time_limits])
  print "Turn Time Limits: %s" % ", ".join([str(val) for val in turn_time_limits])
  if export_to_csv:
    print "Exporting results to CSV: '%s'" % export_to_csv
  print

  results = playTournament(agent_names, setup_time_limits, turn_time_limits, max_turns)

  printSummary(results)
  if export_to_csv:
    exportResultsToCSV(export_to_csv, results)
